use crate::request::RequestModel;
use std::{
    sync::{Arc, Mutex},
    time::Duration,
};
use tokio::{sync::Semaphore, time};

#[allow(dead_code)]
pub struct Client {
    ident: u8,
    /// true -> permited, false -> denied
    status: Mutex<bool>,
}

impl Client {
    pub fn new(ident: u8) -> Self {
        Client {
            ident,
            status: Mutex::new(false),
        }
    }

    pub async fn register(self, client: &RequestModel) -> Result<Self, ()> {
        *self.status.lock().unwrap() = client
            .send(format!("/api/v1/device/register/{}", self.ident))
            .await
            .expect("register device failed")
            .status;

        Ok(self)
    }

    pub fn set(&self, status: bool) {
        let mut locked_status = self.status.lock().expect("can't lock status");
        if *locked_status != status {
            *locked_status = status;
            println!("[Success] {:?}", status);

            // Exact code here .
        }
    }

    pub async fn controlled_poll(
        self,
        interval_secs: u64,
        max_concurent: usize,
        client: &RequestModel,
    ) {
        let semaphore = Arc::new(Semaphore::new(max_concurent));
        let mut interval = time::interval(Duration::from_secs(interval_secs));

        loop {
            interval.tick().await;
            let permit = semaphore.clone().acquire_owned().await.unwrap();

            match client
                .send(format!("/api/v1/device/status/{}", self.ident))
                .await
            {
                Ok(data) => {
                    self.set(data.status);
                }
                Err(_) => println!("[Error]: get status from server"),
            }
            drop(permit);
        }
    }
}
